package ch.mse.android.starbucksfinder;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.Drawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import ch.mse.android.starbucksfinder.helper.DBHelper;
import ch.mse.android.starbucksfinder.helper.GoogleMapsHelper;
import ch.mse.android.starbucksfinder.helper.MessageHelper;
import ch.mse.android.starbucksfinder.ui.BubbleLayout;
import ch.mse.android.starbucksfinder.ui.ItemizedMapOverlay;
import ch.mse.android.starbucksfinder.ui.StarbucksOverlayItem;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapController;
import com.google.android.maps.MapView;
import com.google.android.maps.MyLocationOverlay;
import com.google.android.maps.Overlay;
import com.google.android.maps.OverlayItem;

public class MapActivity extends com.google.android.maps.MapActivity{
	private MapController mapController;
	private static final GeoPoint HSZ_GEOPOINT = new GeoPoint(47377608,8532552);
	
	public static final String LOCATION_LIST_KEY = "location_list";
	public static final String LOCATION_LNG_KEY = "location_lng_key";
	public static final String LOCATION_LAT_KEY = "location_lat_key";
	
	private List<Overlay> mapOverlays;
	private Drawable coffeeMarker;
	private ItemizedMapOverlay itemizedOverlay;
	private MyLocationOverlay myLocationOverlay;
	private MapView mapView;
	private BubbleLayout noteBaloon;
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.map);
        
        this.mapView = (MapView) findViewById(R.id.mapview);
        this.mapView.setBuiltInZoomControls(true);
        this.mapController = mapView.getController();
        this.mapController.setZoom(15);
        this.mapController.setCenter(HSZ_GEOPOINT);
        
        //Prepare overlay resources
        mapOverlays = mapView.getOverlays();
        coffeeMarker = this.getResources().getDrawable(R.drawable.coffee);
        Drawable nearestMarker = this.getResources().getDrawable(R.drawable.coffee_nearest);
        itemizedOverlay = new ItemizedMapOverlay(coffeeMarker,nearestMarker,this);
        myLocationOverlay = new MyLocationOverlay(this,mapView);
        myLocationOverlay.enableMyLocation();
        mapOverlays.add(myLocationOverlay); //when using the emulator you need to call geo fix 8.532552 47.377608 AFTER app map is loaded
        noteBaloon = prepareBubble();
    }


	@Override
	protected void onStart() {
		super.onStart();
		//Register for location update
		LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, new GeoUpdateHandler());
		Location loc = getLocation();
		if(loc==null){
			MessageHelper.displayAlertMessage(this,"Error","Couldn't get location.",new Command() {
				public void perform() {
					finish();
				}
			});
		} else {
			addStarbucksOverlays();
			StarbucksLocation nearestStore = getNearestStores(loc).get(0);
			itemizedOverlay.setNearest(nearestStore);
	        //To test location manager you need to enter gps data: 
	        //telnet localhost 5554 --> geo fix 8.532552 47.377608
	        
	        //TODO display route http://stackoverflow.com/questions/4408671/android-draw-route-on-a-mapview-with-twoo-poi-s
		}
	}
	
	@Override
	public boolean onCreateOptionsMenu(Menu menu){
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.xml.menu, menu);
        return super.onCreateOptionsMenu(menu);
	}
	
    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch(item.getItemId()){
            case R.id.route:
            	Location currLoc = getLocation();
            	StarbucksLocation nearestStoreLoc = getNearestStores(currLoc).get(0);
				startActivity(GoogleMapsHelper.getMapsRouteIntent(currLoc, nearestStoreLoc));
                break;
            case R.id.location_list:
            	Intent myIntent = new Intent(this, LocationListActivity.class);
            	Bundle bundle = new Bundle();
            	Location loc = getLocation();
            	bundle.putSerializable(LOCATION_LIST_KEY, getNearestStores(loc));
            	bundle.putDouble(LOCATION_LAT_KEY, loc.getLatitude());
            	bundle.putDouble(LOCATION_LNG_KEY, loc.getLongitude());
				myIntent.putExtras(bundle);
				startActivityForResult(myIntent, 0);
            	break;
        }
        return super.onOptionsItemSelected(item);
    }

	@Override
	protected boolean isRouteDisplayed() {
		return false;
	}
	
	private ArrayList<StarbucksLocation> getNearestStores(final Location mylocation){
		DBHelper dbhelper = new DBHelper(this.getApplicationContext());
		ArrayList<StarbucksLocation> stores = dbhelper.getStores();
		Collections.sort(stores, new Comparator<StarbucksLocation>() {
			public int compare(StarbucksLocation first, StarbucksLocation second) {
				return Float.valueOf(first.distanceTo(mylocation)).compareTo(second.distanceTo(mylocation));
			}
		});
		return stores;
	}

	private Location getLocation() {
		// Get the location manager
		LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
		// Define the criteria how to select the locatioin provider -> use default
		Criteria criteria = new Criteria();
		String provider = locationManager.getBestProvider(criteria, false);
		Location location = locationManager.getLastKnownLocation(provider);
		
		if (location != null) {
			System.out.println("Provider " + provider + " has been selected.");
			System.out.println((int) (location.getLatitude()));
			System.out.println((int) (location.getLongitude()));
		} 
		return location;
	}

	private void addStarbucksOverlays() {		
        DBHelper dbhelper = new DBHelper(this.getApplicationContext());
        List<StarbucksLocation> storeList = dbhelper.getStores();
        for (StarbucksLocation location : storeList) {
            itemizedOverlay.addOverlay(new StarbucksOverlayItem(location));
            mapOverlays.add(itemizedOverlay);
		}
	}
	
	public void displayBubble(StarbucksOverlayItem item) {
		mapView.removeView(noteBaloon);
		noteBaloon.setVisibility(View.VISIBLE);
		TextView textTitle = (TextView) noteBaloon.findViewById(R.id.bubble_label);
		TextView textmsg = (TextView) noteBaloon.findViewById(R.id.bubble_text);
		textTitle.setText(item.getTitle());
		int meters = Math.round(item.getLocation().distanceTo(getLocation()));
		textmsg.setText(item.getSnippet() + "\n\n" + "Distance: " + meters + "m");
		MapView.LayoutParams layoutParams = new MapView.LayoutParams(BubbleLayout.DEFAULT_WIDTH,BubbleLayout.DEFAULT_HEIGHT,item.getPoint(),MapView.LayoutParams.BOTTOM_CENTER);
		mapView.addView(noteBaloon, layoutParams);
	}


	private BubbleLayout prepareBubble() {
		LayoutInflater layoutInflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		final BubbleLayout noteBaloon = (BubbleLayout) layoutInflater.inflate(R.layout.bubble_layout, null);
		RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(BubbleLayout.DEFAULT_WIDTH,BubbleLayout.DEFAULT_HEIGHT); 
		layoutParams.addRule(RelativeLayout.CENTER_VERTICAL);
		layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
		noteBaloon.setLayoutParams(layoutParams);
		ImageView closeBtn = (ImageView) noteBaloon.findViewById(R.id.close_button);
		closeBtn.setOnClickListener(new View.OnClickListener() {
			public void onClick(View v) {
				mapView.removeView(noteBaloon);
			}
		});
		return noteBaloon;
	}

	private class GeoUpdateHandler implements LocationListener {

		public void onLocationChanged(Location location) {
			int lat = (int) (location.getLatitude() * 1E6);
			int lng = (int) (location.getLongitude() * 1E6);
			GeoPoint point = new GeoPoint(lat, lng);
			mapController.animateTo(point); //	mapController.setCenter(point);
			
			StarbucksLocation nearestStore = getNearestStores(location).get(0);
			itemizedOverlay.setNearest(nearestStore);
		}

		public void onProviderDisabled(String provider) {
		}
		public void onProviderEnabled(String provider) {
		}
		public void onStatusChanged(String provider, int status, Bundle extras) {
		}
	}
}
